home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
download.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
9KB
|
358 lines
/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
$Id: download.c,v 1.56 2001/02/15 08:39:45 drscholl Exp $ */
#include <string.h>
#include "opennap.h"
#include "debug.h"
/* 203 [ :<sender> ] <nick> "<filename>" */
/* 500 [ :<sender> ] <nick> "<filename>" */
/* handle client request for download of a file */
HANDLER (download)
{
char *av[2], *sender_name;
USER *user, *sender;
DATUM *info = 0;
int ac = -1;
(void) len;
ASSERT (validate_connection (con));
if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
return;
if (pkt)
ac = split_line (av, sizeof (av) / sizeof (char *), pkt);
if (ac < 2)
{
unparsable (con);
return;
}
/* find the user to download from */
user = hash_lookup (Users, av[0]);
if (!user)
{
send_user (sender, MSG_SERVER_SEND_ERROR, "%s \"%s\"", av[0], av[1]);
return;
}
/* if the user holding the requested file is local... */
if (ISUSER (user->con))
{
if (is_ignoring (user->con->uopt->ignore, sender->nick))
{
send_user (sender, MSG_SERVER_NOSUCH, "%s is ignoring you",
user->nick);
return;
}
/* check to make sure the user is actually sharing this file */
info = hash_lookup (user->con->uopt->files, av[1]);
if (!info)
{
send_user (sender, MSG_SERVER_SEND_ERROR, "%s \"%s\"",
user->nick, av[1]);
return;
}
}
if (tag == MSG_CLIENT_DOWNLOAD)
{
if (user->port == 0)
{
/* uploader is firewalled, send file info so that downloader can
send the 500 request */
if (ISUSER (user->con))
{
ASSERT (info != 0);
send_user (sender, MSG_SERVER_FILE_READY /* 204 */ ,
"%s %u %hu \"%s\" %s %d", user->nick,
user->ip, user->port, av[1],
#if RESUME
info->hash,
#else
"00000000000000000000000000000000",
#endif
user->speed);
}
else
{
/* not a local user, we have to relay this request since we
dont' have the file information local. route it directly
to the server we know this user is behind. */
ASSERT (ISSERVER (user->con));
send_cmd (user->con, tag, ":%s %s \"%s\"", sender->nick,
user->nick, av[1]);
}
return;
}
}
else
{
ASSERT (tag == MSG_CLIENT_DOWNLOAD_FIREWALL);
if (user->port != 0)
{
/* this user is not firewalled */
send_user (sender, MSG_SERVER_NOSUCH, "%s is not firewalled",
user->nick);
return;
}
if (sender->port == 0)
{
/* error, both clients are firewalled */
ASSERT (ISUSER (con));
send_cmd (con, MSG_SERVER_FILE_READY /* 204 */ ,
"%s %u %hu \"%s\" firewallerror %d",
user->nick, user->ip, user->port, av[1], user->speed);
return;
}
}
/* if the client holding the file is a local user, send the request
directly */
if (ISUSER (user->con))
{
send_cmd (user->con, MSG_SERVER_UPLOAD_REQUEST, "%s \"%s\"",
sender->nick, av[1]);
}
/* otherwise pass it to the peer servers for delivery */
else
{
/* don't use direct delivery here because the server the client is
connected to needs to consult their db and rewrite this messsage */
send_cmd (user->con, MSG_SERVER_UPLOAD_REQUEST, ":%s %s \"%s\"",
sender->nick, user->nick, av[1]);
}
}
static USER *
transfer_count_wrapper (CONNECTION * con, char *pkt, int numeric)
{
USER *user;
ASSERT (validate_connection (con));
if (pop_user (con, &pkt, &user))
return 0;
/* relay to peer servers */
pass_message_args (con, numeric, ":%s", user->nick);
return user;
}
/* 220 [ :<user> ] */
HANDLER (upload_start)
{
USER *user;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
user = transfer_count_wrapper (con, pkt, MSG_CLIENT_UPLOAD_START);
if (!user)
return;
ASSERT (validate_user (user));
user->uploads++;
user->totalup++;
}
/* 221 [ :<user> ] */
HANDLER (upload_end)
{
USER *user;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
user = transfer_count_wrapper (con, pkt, MSG_CLIENT_UPLOAD_END);
if (!user)
return;
ASSERT (validate_user (user));
if (user->uploads > 0)
user->uploads--;
}
/* 218 [ :<user> ] */
HANDLER (download_start)
{
USER *user;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
user = transfer_count_wrapper (con, pkt, MSG_CLIENT_DOWNLOAD_START);
if (!user)
return;
ASSERT (validate_user (user));
user->downloads++;
user->totaldown++;
}
/* 219 [ :<user> ] */
HANDLER (download_end)
{
USER *user;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
user = transfer_count_wrapper (con, pkt, MSG_CLIENT_DOWNLOAD_END);
if (!user)
return;
ASSERT (validate_user (user));
if (user->downloads > 0)
user->downloads--;
}
/* 600 <user> */
/* client is requesting the link speed of <user> */
HANDLER (user_speed)
{
USER *user;
(void) tag;
(void) len;
CHECK_USER_CLASS ("user_speed");
user = hash_lookup (Users, pkt);
if (!user)
{
nosuchuser (con);
return;
}
ASSERT (validate_user (user));
send_cmd (con, MSG_SERVER_USER_SPEED /* 601 */ , "%s %d",
user->nick, user->speed);
}
/* 626 [ :<nick> ] <user> */
/* client is notifying other party of a failure to connect to their data
port */
HANDLER (data_port_error)
{
USER *sender, *user;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
if (pop_user (con, &pkt, &sender) != 0)
return;
ASSERT (validate_user (sender));
user = hash_lookup (Users, pkt);
if (!user)
{
nosuchuser (con);
return;
}
ASSERT (validate_user (user));
/* we pass this message to all servers so the mods can see it */
pass_message_args (con, tag, ":%s %s", sender->nick, user->nick);
notify_mods
(PORTLOG_MODE,
"Notification from %s: %s (%s) - configured data port %hu is unreachable.",
sender->nick, user->nick, my_ntoa (BSWAP32 (user->ip)), user->port);
/* if local, notify the target of the error */
if (user->local)
send_cmd (user->con, tag, "%s", sender->nick);
}
/* 607 :<sender> <recip> "<filename>" [speed] */
HANDLER (upload_request)
{
char *av[3], *sender_name;
USER *recip, *sender;
int ac = -1;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
CHECK_SERVER_CLASS ("upload_request");
if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
return;
if (pkt)
ac = split_line (av, sizeof (av) / sizeof (char *), pkt);
if (ac < 2)
{
log ("upload_request: too few args");
return;
}
recip = hash_lookup (Users, av[0]);
if (!recip)
{
log ("upload_request: %s: no such user", av[0]);
return;
}
ASSERT (validate_user (recip));
/* if local user, deliver the message */
if (ISUSER (recip->con))
{
/* make sure the user is actually sharing this file */
DATUM *info = hash_lookup (recip->con->uopt->files, av[1]);
if (!info)
{
log ("upload_request: %s is not sharing %s", recip->nick, av[1]);
return;
}
send_cmd (recip->con, MSG_SERVER_UPLOAD_REQUEST /* 607 */ ,
"%s \"%s\" %d", sender->nick, av[1], sender->speed);
}
else
{
/* route the request to the server which the uploader is behind */
send_cmd (recip->con, MSG_SERVER_UPLOAD_REQUEST,
":%s %s \"%s\" %d", sender->nick, recip->nick, av[1],
sender->speed);
}
}
/* 619 <nick> <filename> <limit> */
HANDLER (queue_limit)
{
char *av[3];
int ac;
USER *recip;
DATUM *info;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
CHECK_USER_CLASS ("queue_limit");
ac = split_line (av, sizeof (av) / sizeof (char *), pkt);
if (ac != 3)
{
log ("queue_limit(): wrong number of parameters");
print_args (ac, av);
unparsable (con);
return;
}
recip = hash_lookup (Users, av[0]);
if (!recip)
{
nosuchuser (con);
return;
}
ASSERT (validate_user (recip));
ASSERT (validate_connection (recip->con));
/* look up the filesize in the db */
info = hash_lookup (con->uopt->files, av[1]);
if (!info)
{
send_cmd (con, MSG_SERVER_NOSUCH, "Not sharing that file");
return;
}
/* deliver to user even if remote */
send_user (recip, MSG_SERVER_LIMIT, "%s \"%s\" %u %s",
con->user->nick, av[1], info->size, av[2]);
}